import Axios, {AxiosRequestConfig, AxiosResponse} from 'axios';
import {Loading, Message, MessageBox} from 'element-ui';
import store from '@/store';
import Qs from 'qs';
import router from "@/router";
import storeUtils from "@/utils/storeUtils";

/**
 * http请求工具类
 *
 * 请求拦截器 负责将客户端标识token值存储并放置在头部提交给服务端
 *
 * 响应拦截器 负责全局处理业务请求的网络或者业务错误
 */
let loadingInstance: any;


// 创建axios的实例
const service = Axios.create({
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    baseURL: process.env.VUE_APP_BASE_API, // api的base_url
    timeout: 10000, // 超时时间
    // `paramsSerializer` 是一个负责 `params` 序列化的函数
    // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
    paramsSerializer: function (params) {
        return Qs.stringify(params, {arrayFormat: 'repeat'});//针对get 和 delete 方法参数序列化
    },
    transformRequest: [function (params) {
        // 对 data 进行任意转换处理
        return Qs.stringify(params, {arrayFormat: 'repeat'});// 针对post和put方法参数序列化
    }],
});

// 请求拦截
service.interceptors.request.use((config: AxiosRequestConfig) => {
        if ((config.params && config.params.loading === undefined) || (config.params && config.params.loading !== undefined && config.params.loading === true)) {
            loadingInstance = Loading.service({fullscreen: true, background: 'rgba(0, 0, 0, 0.7)'});
        }
        // 发送请求前添加token信息
        if (store.getters.token) {  // 每次发送请求之前判断是否存在token，如果存在，则统一在http请求的header都加上token，不用每次请求都手动添加了
            config.headers.Authorization = store.getters.token;
        }
        return config;
    },
    (err: any) => {
        return Promise.reject(err);
    }
);

// 响应拦截
service.interceptors.response.use(
    (response: AxiosResponse) => {
        if (loadingInstance) {
            loadingInstance.close();
        }

        if (response.status === 200) {
            if (response.headers && response.headers['authorization']) {
                store.commit('SET_TOKEN', response.headers['authorization']);
            }
            if (response.data) {
                if (response.data.code === 200) {
                    // 对响应数据做点什么
                    return Promise.resolve(response.data);
                }
            }
        }
        if ((!response.config.params || (response.config.params && (response.config.params.isShowMsg === undefined || response.config.params.isShowMsg === true))) && response.data && response.data.msg) {
            Message.warning(response.data.msg);
        }
        return Promise.reject(response.data);
    },
    (err: any) => {
        if (loadingInstance) {
            loadingInstance.close();
        }

        let errMsg = '';
        if (err && err.response && err.response.status) {
            switch (err.response.status) {
                case 400:
                    errMsg = '请求参数错误';
                    break;

                case 401:
                    errMsg = '登录状态失效，请重新登录';
                    if (router.currentRoute.path !== '/login') {
                        MessageBox.confirm(
                            '登录状态已过期，您可以继续留在该页面，或者重新登录',
                            '系统提示',
                            {
                                confirmButtonText: '重新登录',
                                cancelButtonText: '取消',
                                type: 'warning'
                            }
                        ).then(() => {
                            store.dispatch('FedLogOut').then(() => {
                                location.reload() // 为了重新实例化vue-router对象 避免bug
                            })
                        });
                    } else {
                        storeUtils.clearStore();
                        location.reload() // 为了重新实例化vue-router对象 避免bug
                    }
                    return Promise.reject(err.response);
                case 403:
                    errMsg = '拒绝访问';
                    break;

                case 408:
                    errMsg = '请求超时';
                    break;

                case 500:
                    errMsg = '服务器内部错误';
                    break;

                case 501:
                    errMsg = '服务未实现';
                    break;

                case 502:
                    errMsg = '网关错误';
                    break;

                case 503:
                    errMsg = '服务不可用';
                    break;

                case 504:
                    errMsg = '网关超时';
                    break;

                case 505:
                    errMsg = 'HTTP版本不受支持';
                    break;

                default:
                    errMsg = err.response.data.msg;
                    break;
            }
        } else {
            if (err.code === 'ECONNABORTED') {
                errMsg = '请求超时';
            } else {
                errMsg = err.message;
            }
        }
        if ((err && err.response && err.response.config && err.response.config.params && err.response.config.params.isShowErrorMsg !== false) || err.code === 'ECONNABORTED') {
            Message.error(errMsg);
        }
        return Promise.reject(err.response);
    }
);

export default service;
